home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-27 | 6.1 KB | 279 lines | [TEXT/MPS ] |
-
- #include "TCP.h"
- #include "InetD.h"
-
- #include <UFailure.h>
-
- #include <Resources.h>
- #include <Devices.h>
- #include <Processes.h>
-
- TCPListener::TCPListener(InetD* daemon)
- {
- fDaemon = daemon;
- fBufferSize = 0;
- }
-
- TCPListener::~TCPListener()
- {
- this->Release();
- }
-
- /* I'm assigning the result of a memory allocation directly to a
- field, but its okay. The class isn't declared as a HandleObject
- because I need to get at it during interrupt.
- */
- Boolean
- TCPListener::Initialize()
- {
- int numPBs;
- int i;
-
- Handle resHandle;
- short theID;
- ResType theType;
- Str255 theName;
-
- resHandle = GetResource('BUFF', 128);
- FailResError();
- fBufferSize = *((int*) *resHandle);
-
- numPBs = CountResources('TCP ');
- if (numPBs > 0) {
- if (!fQueue.AllocPBs(numPBs, sizeof(MyTCPiopb)))
- FailNIL((void*) 0);
-
- for (i = 1; i <= numPBs; i++) {
- resHandle = GetIndResource('TCP ', i);
- FailResError();
-
- GetResInfo(resHandle, &theID, &theType, theName);
- this->ListenOn((tcp_port) theID);
-
- ReleaseResource(resHandle);
- }
-
- return true;
- }
- else
- return false;
- }
-
- void
- TCPListener::DoNull()
- {
- MyTCPiopb* pb;
- short port;
- Handle resHandle;
- FailInfo fi;
- PSN dummy;
-
- while ((pb = (MyTCPiopb*) fQueue.GetCompletedPB()) != nil) {
- if ((pb->tcppb.csCode == TCPPassiveOpen) && (pb->tcppb.ioResult == noErr)) {
- port = pb->tcppb.csParam.open.localPort;
-
- resHandle = GetResource('TCP ', port);
- FailResError();
-
- HLock(resHandle);
-
- fDaemon->LogIt(false, "Attempting to launch %P\n", ((FSSpec*) *resHandle)->name);
-
- if (fi.Try()) {
- fDaemon->Launch(pb->tcppb.tcpStream, (FSSpec*) *resHandle, 'TSTR', &dummy);
- fi.Success();
- }
- else {
- this->CloseDown(pb);
- fDaemon->LogIt(true, "InetD:\n\nFailed to launch %P for TCP port %d\n",
- ((FSSpec*) *resHandle)->name, port);
- }
-
- fQueue.RecyclePB((ParmBlkPtr) pb);
-
- this->ListenOn(port);
-
- HUnlock(resHandle);
- ReleaseResource(resHandle);
- }
- else {
- fQueue.RecyclePB((ParmBlkPtr) pb);
- }
- }
- }
-
- void
- TCPListener::ListenOn(tcp_port thePort)
- {
- MyTCPiopb* pb = nil;
- Ptr rcvPtr = nil;
-
- rcvPtr = NewPtrSys(fBufferSize);
- FailMemError();
-
- pb = (MyTCPiopb*) fQueue.GetUnusedPB();
- FailNIL(pb);
-
- pb->myA5 = SetCurrentA5();
- pb->listener = this;
-
- pb->tcppb.csCode = TCPCreate;
- pb->tcppb.ioCRefNum = fDaemon->GetDriver();
- pb->tcppb.csParam.create.rcvBuff = rcvPtr;
- pb->tcppb.csParam.create.rcvBuffLen = fBufferSize;
- pb->tcppb.csParam.create.notifyProc = &TCPNotify;
- pb->tcppb.csParam.create.userDataPtr = (Ptr) this;
-
- FailOSErr(PBControlSync((ParmBlkPtr) pb));
-
- pb->tcppb.csCode = TCPPassiveOpen;
- pb->tcppb.ioCRefNum = fDaemon->GetDriver();
- pb->tcppb.ioCompletion = &TCPCompletion;
- pb->tcppb.csParam.open.ulpTimeoutValue = 0;
- pb->tcppb.csParam.open.ulpTimeoutAction = 1;
- pb->tcppb.csParam.open.validityFlags = 0xC0;
- pb->tcppb.csParam.open.commandTimeoutValue = 0;
- pb->tcppb.csParam.open.remoteHost = 0;
- pb->tcppb.csParam.open.remotePort = 0;
- pb->tcppb.csParam.open.localHost = 0;
- pb->tcppb.csParam.open.localPort = thePort;
- pb->tcppb.csParam.open.tosFlags = 0;
- pb->tcppb.csParam.open.precedence = 0;
- pb->tcppb.csParam.open.dontFrag = 0;
- pb->tcppb.csParam.open.timeToLive = 0;
- pb->tcppb.csParam.open.security = 0;
- pb->tcppb.csParam.open.optionCnt = 0;
-
- FailOSErr(PBControlAsync((ParmBlkPtr) pb));
- }
-
- void
- TCPListener::CloseDown(MyTCPiopb* pb)
- {
- pb->tcppb.csCode = TCPClose;
- pb->tcppb.ioCRefNum = fDaemon->GetDriver();
- pb->tcppb.csParam.close.ulpTimeoutValue = 3;
- pb->tcppb.csParam.close.ulpTimeoutAction = 0;
- pb->tcppb.csParam.close.validityFlags = 0xC0;
- pb->tcppb.csParam.close.userDataPtr = nil;
-
- FailOSErr(PBControlSync((ParmBlkPtr) pb));
-
- pb->tcppb.csCode = TCPRelease;
- pb->tcppb.csParam.create.userDataPtr = nil;
-
- FailOSErr(PBControlSync((ParmBlkPtr) pb));
-
- DisposePtr(pb->tcppb.csParam.create.rcvBuff);
- FailMemError();
- }
-
- /* This actually does the Right Thing. The CQueue class is designed
- specifically for handling system parameter blocks and keeps track
- of them through various states of progress. The CleanQs function
- only return PBs that are in use, in progress, or completed but
- awaiting processing - not unused PBs.
- */
- void
- TCPListener::Release()
- {
- MyTCPiopb* pb = nil;
-
- while ((pb = (MyTCPiopb*) fQueue.CleanQs()) != nil)
- this->CloseDown(pb);
- }
-
- void
- TCPListener::NotifyMe(PSNPtr psn, StreamPtr stream, ProcPtr proc, Ptr usr)
- {
- NoteeItem* nu = new NoteeItem;
- FailNIL(nu);
-
- nu->fPSN.highLongOfPSN = psn->highLongOfPSN;
- nu->fPSN.lowLongOfPSN = psn->lowLongOfPSN;
- nu->fStream = stream;
- nu->fProc = proc;
- nu->fUsrPtr = usr;
-
- fNoteeList.PutOn(nu);
- }
-
- /* This currently gets called with the PSN of every app that
- we launch, even the ones that don't request ASR service,
- hence its okay if the notee isn't found.
- */
- void
- TCPListener::UnNotify(PSNPtr psn)
- {
- NoteeItem* old = fNoteeList.GetItem(psn);
- if (old) {
- fNoteeList.TakeOff(old);
- delete old;
- }
- }
-
- NoteeItem::NoteeItem()
- {
- fPSN.highLongOfPSN = 0;
- fPSN.lowLongOfPSN = 0;
- fStream = nil;
- fProc = nil;
- fUsrPtr = nil;
- }
-
- /* Its okay if these don't find the item, see the comment
- on the UnNotify function above.
- */
- NoteeItem*
- NoteeList::GetItem(PSNPtr psn)
- {
- NoteeItem* it = (NoteeItem*) this->First();
-
- while (it && (!SameProcesses(psn, &it->fPSN)))
- it = (NoteeItem*) it->fNext;
-
- // if (it == nil) DebugStr("\pdidn't find it…");
- return it;
- }
-
- NoteeItem*
- NoteeList::GetItem(StreamPtr stream)
- {
- NoteeItem* it = (NoteeItem*) this->First();
-
- while (it && (stream != it->fStream))
- it = (NoteeItem*) it->fNext;
-
- // if (it == nil) DebugStr("\pdidn't find it…");
- return it;
- }
-
- void
- TCPCompletion(TCPiopb* in)
- {
- MyTCPiopb* pb = (MyTCPiopb*) in;
- long thisA5 = SetA5(pb->myA5);
-
- if (pb->tcppb.ioResult == noErr) {
- pb->listener->fQueue.StoreCompletedPB((ParmBlkPtr) pb);
- WakeUpProcess(&pb->listener->fDaemon->fPSN);
- }
-
- SetA5(thisA5);
- }
-
- pascal void
- TCPNotify( StreamPtr stream,
- unsigned short eventCode,
- Ptr usr,
- unsigned short termReason,
- struct ICMPReport* icmp)
- {
- NoteeItem* them;
-
- them = ((TCPListener*) usr)->fNoteeList.GetItem(stream);
- if (them && them->fProc)
- (*(TCPNotifyProc) them->fProc)(stream, eventCode, them->fUsrPtr, termReason, icmp);
- }
-
-